package org.jacoco.core.instr;

import org.jacoco.core.internal.flow.*;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AnalyzerAdapter;
import org.objectweb.asm.util.Printer;

public class MyclassReaderTest {
    public static void main(String[] args) throws Exception{
        ClassReader classReader = new ClassReader("org.jacoco.core.instr.MyTest");
        classReader.accept(new ClassVisitor(Opcodes.ASM6){
            private int cnt = 0;
            @Override
            public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
                if(name.equals("say")){
                    return new MethodSanitizer((MethodVisitor)null, access, name, descriptor, signature, exceptions) {
                        public void visitEnd() {
                            super.visitEnd();
                            LabelFlowAnalyzer.markLabels(this);
                            this.accept( new MethodVisitor(Opcodes.ASM6,mv){
                                @Override
                                public void visitParameter(String name, int access) {
                                    System.out.println("visitParameter");
                                    super.visitParameter(name, access);
                                }

                                @Override
                                public AnnotationVisitor visitAnnotationDefault() {
                                    System.out.println("visitAnnotationDefault");
                                    return super.visitAnnotationDefault();
                                }

                                @Override
                                public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
                                    System.out.println("visitAnnotation");
                                    return super.visitAnnotation(descriptor, visible);
                                }

                                @Override
                                public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
                                    System.out.println("visitTypeAnnotation");
                                    return super.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
                                }

                                @Override
                                public void visitAnnotableParameterCount(int parameterCount, boolean visible) {
                                    super.visitAnnotableParameterCount(parameterCount, visible);
                                    System.out.println("visitAnnotableParameterCount");
                                }

                                @Override
                                public AnnotationVisitor visitParameterAnnotation(int parameter, String descriptor, boolean visible) {
                                    System.out.println("visitParameterAnnotation");
                                    return super.visitParameterAnnotation(parameter, descriptor, visible);

                                }

                                @Override
                                public void visitAttribute(Attribute attribute) {
                                    super.visitAttribute(attribute);
                                    System.out.println("visitAttribute");
                                }

                                @Override
                                public void visitCode() {
                                    super.visitCode();
                                    System.out.println("visitCode");
                                }

                                @Override
                                public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
                                    super.visitFrame(type, nLocal, local, nStack, stack);
                                    System.out.println("visitFrame: "+ Printer.TYPES[type]);
                                }

                                @Override
                                public void visitInsn(int opcode) {
                                    super.visitInsn(opcode);
                                    String mnemonic = Printer.OPCODES[opcode];
                                    System.out.println("visitInsn: "+mnemonic);
                                }

                                @Override
                                public void visitIntInsn(int opcode, int operand) {
                                    super.visitIntInsn(opcode, operand);
                                    String mnemonic = Printer.OPCODES[opcode];
                                    System.out.println("visitIntInsn: "+mnemonic+" "+operand);
                                }

                                @Override
                                public void visitVarInsn(int opcode, int var) {
                                    super.visitVarInsn(opcode, var);
                                    String mnemonic = Printer.OPCODES[opcode];
                                    System.out.println("visitVarInsn: "+mnemonic+" "+var);
                                }

                                @Override
                                public void visitTypeInsn(int opcode, String type) {
                                    super.visitTypeInsn(opcode, type);
                                    String mnemonic = Printer.OPCODES[opcode];
                                    System.out.println("visitTypeInsn: "+mnemonic+" "+type);
                                }

                                @Override
                                public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
                                    super.visitFieldInsn(opcode, owner, name, descriptor);
                                    System.out.println("visitFieldInsn: "+Printer.OPCODES[opcode]+ " "+owner+" "+name);
                                }

                                @Override
                                public void visitMethodInsn(int opcode, String owner, String name, String descriptor) {
                                    super.visitMethodInsn(opcode, owner, name, descriptor);
                                    System.out.println("visitMethodInsn: "+Printer.OPCODES[opcode]);
                                }

                                @Override
                                public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
                                    super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
                                    System.out.println("visitMethodInsn: "+Printer.OPCODES[opcode] +" "+owner +" "+name);
                                }

                                @Override
                                public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
                                    super.visitInvokeDynamicInsn(name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments);
                                    System.out.println("visitInvokeDynamicInsn");
                                }

                                @Override
                                public void visitJumpInsn(int opcode, Label label) {
                                    super.visitJumpInsn(opcode, label);
                                    String mnemonic = Printer.OPCODES[opcode];
                                    System.out.println("visitJumpInsn: "+mnemonic+" "+label);
                                }

                                @Override
                                public void visitLabel(Label label) {
                                    super.visitLabel(label);
                                    System.out.println("--> visitLabel: "+label+", info: "+label.info);
                                }

                                @Override
                                public void visitLdcInsn(Object value) {
                                    super.visitLdcInsn(value);
                                    System.out.println("visitLdcInsn: "+value);
                                }

                                @Override
                                public void visitIincInsn(int var, int increment) {
                                    super.visitIincInsn(var, increment);
                                    System.out.println("visitIincInsn");
                                }

                                @Override
                                public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
                                    super.visitTableSwitchInsn(min, max, dflt, labels);
                                    System.out.println("visitTableSwitchInsn");
                                }

                                @Override
                                public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
                                    System.out.println("visitLookupSwitchInsn");
                                    super.visitLookupSwitchInsn(dflt, keys, labels);
                                }

                                @Override
                                public void visitMultiANewArrayInsn(String descriptor, int numDimensions) {
                                    System.out.println("visitMultiANewArrayInsn");
                                    super.visitMultiANewArrayInsn(descriptor, numDimensions);
                                }

                                @Override
                                public AnnotationVisitor visitInsnAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
                                    System.out.println("visitInsnAnnotation");
                                    return super.visitInsnAnnotation(typeRef, typePath, descriptor, visible);
                                }

                                @Override
                                public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
                                    System.out.println("visitTryCatchBlock: start="+start+" end="+end+" handler="+handler+" type="+type);
                                    super.visitTryCatchBlock(start, end, handler, type);
                                }

                                @Override
                                public AnnotationVisitor visitTryCatchAnnotation(int typeRef, TypePath typePath, String descriptor, boolean visible) {
                                    System.out.println("visitTryCatchAnnotation");
                                    return super.visitTryCatchAnnotation(typeRef, typePath, descriptor, visible);
                                }

                                @Override
                                public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
                                    super.visitLocalVariable(name, descriptor, signature, start, end, index);
                                    System.out.println("visitLocalVariable: "+name);
                                }

                                @Override
                                public AnnotationVisitor visitLocalVariableAnnotation(int typeRef, TypePath typePath, Label[] start, Label[] end, int[] index, String descriptor, boolean visible) {
                                    System.out.println("visitLocalVariableAnnotation");
                                    return super.visitLocalVariableAnnotation(typeRef, typePath, start, end, index, descriptor, visible);
                                }

                                @Override
                                public void visitLineNumber(int line, Label start) {
                                    super.visitLineNumber(line, start);
                                    System.out.println("visitLineNumber:"+line+","+start);
                                }

                                @Override
                                public void visitMaxs(int maxStack, int maxLocals) {
                                    super.visitMaxs(maxStack, maxLocals);
                                    System.out.println("visitMaxs: maxStack="+maxStack+",maxLocals="+maxLocals);
                                }

                                @Override
                                public void visitEnd() {
                                    super.visitEnd();
                                    System.out.println("visitEnd");
                                }
                            });
                        }
                    };
                }else{
                    return mv;
                }

            }
        },0);
    }
}